require "erb"
include ERB::Util

# Sign in twitter, basado en:
# https://dev.twitter.com/docs/auth/implementing-sign-twitter

# TODO: explicar qué hace cada paso, para que sirve cada parámetro, separar en vistas distintas cada paso
# TODO poner response status para cada request

CONSUMER_SECRET = "EDUcnNFGa0GMjVLBtQkRk70kPeO0WvK6NkpaxZ0U4"

class TweetsController < ApplicationController

  # Calcula la firma según https://dev.twitter.com/docs/auth/creating-signature
  def calculate_signature(metodo, url, parametros, token_secret)

    # Encodeo los parametros
    parametros_aux = Hash.new
    parametros.each {|key, value| parametros_aux[url_encode(key)] = url_encode(value)}

    # Ordeno los parametros    
    claves = Array.new
    parametros_aux.each_key {|key| claves.push(key) }
    claves.sort!
  
    # Concateno clave y valor de todos los parámetros en un string
    cadena = ""
    claves.each {|c| cadena += c + "=" + parametros_aux[c] + "&"}
    cadena = cadena[0..cadena.length - 2]

    # Armo la firma: Método & url & parámetros
    signature = metodo.upcase + "&" + url_encode(url) + "&" + url_encode(cadena)
    
    # Armo la clave según si es request_token u otro
    signing_key = url_encode(CONSUMER_SECRET) + "&" + (token_secret ? url_encode(token_secret) : "")

    # Calculo la firma
    digest = OpenSSL::Digest::Digest.new('sha1')
    signature = ActiveSupport::Base64.encode64s(OpenSSL::HMAC.digest(digest, signing_key, signature))
  end

  def index
    
  end

  # Step 1: Obtaining a request token
  def obtener_request_token
    metodo = 'POST'
    url = 'https://api.twitter.com/oauth/request_token'
  
    parametros = Hash.new
    parametros["oauth_callback"] = "http://127.0.0.1:3000/tweets/callback"
    parametros["oauth_consumer_key"] = "QxxZPEYi0tjduCdEMVCYFQ"
    parametros["oauth_nonce"] = (0...32).map{ ('a'..'z').to_a[rand(26)] }.join
    parametros["oauth_signature_method"] = "HMAC-SHA1"
    parametros["oauth_timestamp"] = Time.now.utc.to_i.to_s
    parametros["oauth_version"] = "1.0"
    parametros["oauth_signature"] = calculate_signature(metodo, url, parametros, nil)

    claves = Array.new
    parametros.each_key {|key| claves.push(key) }
    claves.sort!

    header = "OAuth "
    claves.each {|key| header += key + "=\"" + url_encode(parametros[key]) + "\"," }
    header = header[0..(header.length - 2)]

    conn = Faraday.new#(:proxy => 'http://10.20.0.4:8080')
    response = conn.post do |req|
      req.url url
      req.headers['Authorization'] = header
    end

    # TODO manejo de errores, ver que devuelva 200 response.status

    respuesta = Rack::Utils.parse_nested_query(response.body)
    session['oauth_token'] = respuesta['oauth_token']
    session['oauth_token_secret'] = respuesta['oauth_token_secret']
    session['oauth_callback_confirmed'] = respuesta['oauth_callback_confirmed']

    render :index
  end

  # Step 2: Redirecting the user
  def redirigir_usuario
    url = 'https://api.twitter.com/oauth/authenticate'
    url += '?oauth_token=' + session['oauth_token']
  
    redirect_to (url)
  end

  def callback
    # TODO validar que el oauth_token recibido sea el mismo que el del paso 1
    #session['oauth_token_2'] == session['oauth_token']

    session['oauth_token_2'] = params[:oauth_token]
    session['oauth_verifier'] = params[:oauth_verifier]
  
    render :index
  end

  # Step 3: Converting the request token to an access token
  def obtener_access_token
    metodo = 'POST'
    url = 'https://api.twitter.com/oauth/access_token'
  
    parametros = Hash.new
    parametros["oauth_consumer_key"] = "QxxZPEYi0tjduCdEMVCYFQ"
    parametros["oauth_nonce"] = (0...32).map{ ('a'..'z').to_a[rand(26)] }.join
    parametros["oauth_signature_method"] = "HMAC-SHA1"
    parametros["oauth_timestamp"] = Time.now.utc.to_i.to_s
    parametros["oauth_token"] = session['oauth_token_2']
    parametros["oauth_version"] = "1.0"
    parametros["oauth_signature"] = calculate_signature(metodo, url, parametros, session['oauth_token_secret'])

    claves = Array.new
    parametros.each_key {|key| claves.push(key) }
    claves.sort!

    header = "OAuth "
    claves.each {|key| header += key + "=\"" + url_encode(parametros[key]) + "\"," }
    header = header[0..(header.length - 2)]

    conn = Faraday.new#(:proxy => 'http://10.20.0.4:8080')
    response = conn.post do |req|
      req.url url
      req.body = 'oauth_verifier=' + session['oauth_verifier']
      req.headers['Authorization'] = header
    end

    respuesta = Rack::Utils.parse_nested_query(response.body)

    session['oauth_token_3'] = respuesta['oauth_token']
    session['oauth_token_secret_3'] = respuesta['oauth_token_secret']

    # TODO manejar errores: ver response.status y mostrar error

    render :index
  end

  def tweet
    metodo = 'POST'
    url = 'https://api.twitter.com/1.1/statuses/update.json'
  
    parametros = Hash.new
    parametros["oauth_consumer_key"] = "QxxZPEYi0tjduCdEMVCYFQ"
    parametros["oauth_nonce"] = (0...32).map{ ('a'..'z').to_a[rand(26)] }.join
    parametros["oauth_signature_method"] = "HMAC-SHA1"
    parametros["oauth_timestamp"] = Time.now.utc.to_i.to_s
    parametros["oauth_token"] = session['oauth_token_3']
    parametros["oauth_version"] = "1.0"
    parametros["status"] = params[:texto]
    parametros["oauth_signature"] = calculate_signature(metodo, url, parametros, session['oauth_token_secret_3'])

    parametros.except!("status")

    claves = Array.new
    parametros.each_key {|key| claves.push(key) }
    claves.sort!

    header = "OAuth "
    claves.each {|key| header += key + "=\"" + url_encode(parametros[key]) + "\"," }
    header = header[0..(header.length - 2)]

    conn = Faraday.new#(:proxy => 'http://10.20.0.4:8080')
    response = conn.post do |req|
      req.url url
      req.body = 'status=' + url_encode(params[:texto])
      req.headers['Authorization'] = header
    end

    @result = response.status

    render :index
  end
  
end
